<!DOCTYPE html>
<html lang="en">
<head>
    
    <meta charset="utf-8">
    <title>BatchTaskRunner.js - Aliwork helper</title>
    
    <meta name="description" content="宜搭前端 JS 工具代码库" />
    
        <meta name="keywords" content="Aliwork 宜搭 工具库" />
        <meta name="keyword" content="Aliwork 宜搭 工具库" />
    
    
    
    <script src="scripts/prettify/prettify.js"></script>
    <script src="scripts/prettify/lang-css.js"></script>
    <!--[if lt IE 9]>
      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
    <link type="text/css" rel="stylesheet" href="styles/prettify.css">
    <link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
    <script src="scripts/nav.js" defer></script>
    
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>

<input type="checkbox" id="nav-trigger" class="nav-trigger" />
<label for="nav-trigger" class="navicon-button x">
  <div class="navicon"></div>
</label>

<label for="nav-trigger" class="overlay"></label>

<nav >
    
    <input type="text" id="nav-search" placeholder="Search" />
    
    
    <h2><a href="index.html">Home</a></h2><h2><a href="https://github.com/hackingzhang/aliwork-helper" target="_blank" class="menu-item" >Github</a></h2><h2><a href="https://gitee.com/hexzhangshuai/aliwork-helper" target="_blank" class="menu-item" >Gitee码云</a></h2><h2><a href="https://docs.aliwork.com/docs/developer/api/about" target="_blank" class="menu-item" >宜搭开放API</a></h2><h3>Modules</h3><ul><li><a href="module-BatchTaskRunner.html">BatchTaskRunner</a></li><li><a href="module-DataLinkage.html">DataLinkage</a><ul class='methods'><li data-type='method'><a href="module-DataLinkage.html#.dataLinkage">dataLinkage</a></li><li data-type='method'><a href="module-DataLinkage.html#.dataLinkageSubform">dataLinkageSubform</a></li><li data-type='method'><a href="module-DataLinkage.html#~resolveConditionMap">resolveConditionMap</a></li></ul></li><li><a href="module-DataSource.html">DataSource</a><ul class='methods'><li data-type='method'><a href="module-DataSource.html#.deleteFormData">deleteFormData</a></li><li data-type='method'><a href="module-DataSource.html#.executeTask">executeTask</a></li><li data-type='method'><a href="module-DataSource.html#.fetchSubformDatas">fetchSubformDatas</a></li><li data-type='method'><a href="module-DataSource.html#.fetchSubformDatasAll">fetchSubformDatasAll</a></li><li data-type='method'><a href="module-DataSource.html#.getFormData">getFormData</a></li><li data-type='method'><a href="module-DataSource.html#.getOperationRecords">getOperationRecords</a></li><li data-type='method'><a href="module-DataSource.html#.invokeConnector">invokeConnector</a></li><li data-type='method'><a href="module-DataSource.html#.saveFormData">saveFormData</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDataIds">searchFormDataIds</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDataIdsAll">searchFormDataIdsAll</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDatas">searchFormDatas</a></li><li data-type='method'><a href="module-DataSource.html#.searchFormDatasAll">searchFormDatasAll</a></li><li data-type='method'><a href="module-DataSource.html#.startInstance">startInstance</a></li><li data-type='method'><a href="module-DataSource.html#.updateFormData">updateFormData</a></li></ul></li><li><a href="module-Field.html">Field</a><ul class='methods'><li data-type='method'><a href="module-Field.html#.activateTabItems">activateTabItems</a></li><li data-type='method'><a href="module-Field.html#.fieldToString">fieldToString</a></li><li data-type='method'><a href="module-Field.html#.fieldValueDiff">fieldValueDiff</a></li><li data-type='method'><a href="module-Field.html#.fieldValueEqualSingle">fieldValueEqualSingle</a></li><li data-type='method'><a href="module-Field.html#.generateAssociationFormFieldData">generateAssociationFormFieldData</a></li><li data-type='method'><a href="module-Field.html#.generateDptFieldData">generateDptFieldData</a></li><li data-type='method'><a href="module-Field.html#.generateEmployeeFieldData">generateEmployeeFieldData</a></li><li data-type='method'><a href="module-Field.html#.getFieldDataTypeById">getFieldDataTypeById</a></li><li data-type='method'><a href="module-Field.html#.getFieldTypeById">getFieldTypeById</a></li><li data-type='method'><a href="module-Field.html#.mergeTo">mergeTo</a></li><li data-type='method'><a href="module-Field.html#.syncTo">syncTo</a></li></ul></li><li><a href="module-Subform.html">Subform</a><ul class='methods'><li data-type='method'><a href="module-Subform.html#.associateForm2Subform">associateForm2Subform</a></li><li data-type='method'><a href="module-Subform.html#.sum2Main">sum2Main</a></li><li data-type='method'><a href="module-Subform.html#~resolveFieldMaps">resolveFieldMaps</a></li></ul></li><li><a href="module-UI.html">UI</a><ul class='methods'><li data-type='method'><a href="module-UI.html#.dialog">dialog</a></li><li data-type='method'><a href="module-UI.html#.hijackSubmit">hijackSubmit</a></li><li data-type='method'><a href="module-UI.html#.loading">loading</a></li></ul></li><li><a href="module-Utils.html">Utils</a><ul class='methods'><li data-type='method'><a href="module-Utils.html#.dateTimeFormat">dateTimeFormat</a></li><li data-type='method'><a href="module-Utils.html#.generateRandomId">generateRandomId</a></li><li data-type='method'><a href="module-Utils.html#.isEmpty">isEmpty</a></li><li data-type='method'><a href="module-Utils.html#.retry">retry</a></li><li data-type='method'><a href="module-Utils.html#.round">round</a></li><li data-type='method'><a href="module-Utils.html#.sleep">sleep</a></li></ul></li></ul><h3>Classes</h3><ul><li><a href="FieldChangeLogger.html">FieldChangeLogger</a><ul class='methods'><li data-type='method'><a href="FieldChangeLogger.html#change">change</a></li><li data-type='method'><a href="FieldChangeLogger.html#clear">clear</a></li><li data-type='method'><a href="FieldChangeLogger.html#format">format</a></li></ul></li><li><a href="module-BatchTaskRunner-BatchTaskRunner.html">BatchTaskRunner</a><ul class='methods'><li data-type='method'><a href="module-BatchTaskRunner-BatchTaskRunner.html#_checkTaskProvider">_checkTaskProvider</a></li><li data-type='method'><a href="module-BatchTaskRunner-BatchTaskRunner.html#_doBatchTask">_doBatchTask</a></li><li data-type='method'><a href="module-BatchTaskRunner-BatchTaskRunner.html#_getTask">_getTask</a></li><li data-type='method'><a href="module-BatchTaskRunner-BatchTaskRunner.html#start">start</a></li></ul></li><li><a href="module-Subform-Subform.html">Subform</a><ul class='methods'><li data-type='method'><a href="module-Subform-Subform.html#getDatas">getDatas</a></li><li data-type='method'><a href="module-Subform-Subform.html#getFormGroupId">getFormGroupId</a></li><li data-type='method'><a href="module-Subform-Subform.html#getFormGroupIds">getFormGroupIds</a></li><li data-type='method'><a href="module-Subform-Subform.html#getIndex">getIndex</a></li><li data-type='method'><a href="module-Subform-Subform.html#getInstance">getInstance</a></li><li data-type='method'><a href="module-Subform-Subform.html#getItem">getItem</a></li><li data-type='method'><a href="module-Subform-Subform.html#setDatas">setDatas</a></li><li data-type='method'><a href="module-Subform-Subform.html#summary">summary</a></li><li data-type='method'><a href="module-Subform-Subform.html#updateItem">updateItem</a></li></ul></li></ul>
    
</nav>

<div id="main">
    
    <h1 class="page-title">BatchTaskRunner.js</h1>
    

    



    
    <section>
        <article>
            <pre class="prettyprint source linenums"><code>/**
 * 批量任务运行工具
 * @module BatchTaskRunner
 */

/**
 * 批量任务运行 options 选项
 * @typedef {Object} BatchTaskRunnerOptions
 * @property {Function} beforeBatchCb 批次执行前回调，在执行每个批次任务前调用
 * @property {Function} afterBatchCb 批次执行后回调，在执行完每个批次任务后调用
 */
/**
 * 任务
 * @callback Task
 * @returns {Promise}
 */
/**
 * 函数形式的任务提供者
 * @callback FnTaskProvider
 * @returns {module:BatchTaskRunner~Task}
 */
/**
 * 批量任务运行类
 *
 * @example
 * // 创建一个函数类型的taskProvider，BatchTaskRunner将调用此函数来获取任务
 * const taskProvider = (function () {
 *   let index = 0;
 *   // 生成10个简单的任务，每个任务打印其任务编号
 *   return function() {
 *     let task;
 *     if (index &lt; 10) {
 *       task = (async function() { console.log(`Task ${index + 1}`); });
 *     } else {
 *       task = null;
 *     }
 *   }
 * })();
 *
 * // 批量处理任务，10个任务为一批次
 * new BatchTaskRunner(
 *   taskProvider,
 *   10,
 *   {
 *     beforeBatchCb: () => { console.log("批次开始"); };
 *     afterBatchCb: () => { console.log("批次结束"); };
 *   }
 * ).start();
 */
class BatchTaskRunner {
  /**
   * 构造器
   * @param {Generator&lt;Task> | module:BatchTaskRunner~FnTaskProvider} taskProvider 任务提供者，可以传入一个函数或者生成器。
   * 一个任务就是一个函数，任务函数应当返回一个 Promise，Promise敲定即认定任务结束。&lt;br />
   * 如果任务提供者是一个函数，当此函数返回 falsy 值则认为所有任务都已提供完毕，BatchTaskRunner 将会在执行完最后一个批次后结束。&lt;br />
   * 如果任务提供者是一个生成器，则会遍历生成器来获取任务，遍历完成后 BatchTaskRunner 将会在执行完最后一个批次后结束。
   * @param {number} batchSize 一个批次处理多少任务
   * @param {module:BatchTaskRunner~BatchTaskRunnerOptions} options 选项
   */
  constructor(taskProvider, batchSize, options) {
    this._providerType = this._checkTaskProvider(taskProvider);

    this._taskProvider = taskProvider;
    this._batchSize = batchSize || 1;

    this._options = Object.assign(
      { beforeBatchCb: () => {}, afterBatchCb: () => {} },
      options
    );
  }

  /**
   * @access private
   * 检查 taskProvider 类型，并返回类型字符串。如果任务提供者不符合类型要求则会抛出异常。
   * @param {*} taskProvider 任务提供者
   * @returns {"function" | "generator"}
   */
  _checkTaskProvider(taskProvider) {
    if (typeof taskProvider === "function") {
      return "function";
    } else if (
      Symbol.iterator in taskProvider &amp;&amp;
      typeof taskProvider.next === "function"
    ) {
      return "generator";
    } else {
      throw Error(
        "[BatchTaskRunner] taskProvider MUST be a function or generator"
      );
    }
  }

  /**
   * @access private
   * 从任务提供者获取单个任务
   * @returns {Task}
   */
  _getTask() {
    let task = null;
    switch (this._providerType) {
      case "function":
        task = this._taskProvider();
        break;
      case "generator": {
        const next = this._taskProvider.next();
        task = next.value;
        break;
      }
    }

    return task;
  }

  /**
   * @access private
   * 执行一个批次的批量任务
   * @param {Function[]} tasks
   */
  async _doBatchTask(tasks) {
    this._options.beforeBatchCb();
    const result = await Promise.allSettled(tasks.map((task) => task()));
    this._options.afterBatchCb(result);
  }

  /**
   * 开始批量处理任务
   */
  async start() {
    const tasks = [];
    let task = this._getTask();

    while (task) {
      tasks.push(task);
      if (tasks.length === this._batchSize) {
        await this._doBatchTask(tasks);
        tasks.length = 0;
      }

      task = this._getTask();
      if (!task &amp;&amp; tasks.length) {
        await this._doBatchTask(tasks);
        tasks.length = 0;
      }
    }
  }
}

export { BatchTaskRunner };
</code></pre>
        </article>
    </section>




    
    
</div>

<br class="clear">

<footer>
    Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.2</a> on Wed Jun 19 2024 12:08:14 GMT+0800 (中国标准时间) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
</footer>

<script>prettyPrint();</script>
<script src="scripts/polyfill.js"></script>
<script src="scripts/linenumber.js"></script>

<script src="scripts/search.js" defer></script>



</body>
</html>
